#!/bin/bash

set -e

VERSION=0.4

procartist () {
    for ITEMDIR in "$1"/*
    do
        TARGET=""
        TRACKS=0
        TAGALBUM=""
        TAGALBUMARTIST=""
        TAGDATE=""
        TAGSRCMEDIA=""

        if [[ -d "$ITEMDIR" ]]
        then
            printf "\n"
            echo "[cymusic] processing $ITEMDIR"

            # guess total tracks by mime type
            TRACKS=$(file --mime-type "$ITEMDIR"/* | grep audio | wc -l)
            if [[ $TRACKS == 0 ]]
            then
                echo "[cymusic] [ERROR] no audio files detected"
                exit 1
            else
                echo "[cymusic] detected $TRACKS music tracks"
            fi

            # check and process attributes that affect single files
            for IFILE in "$ITEMDIR"/*
            do
                if file --mime-type "$IFILE" | grep audio &> /dev/null
                then
                    TARGET="$IFILE"

                    # read tags
                    TALBUM="$(kid3-cli -c "get ALBUM" "$TARGET")"
                    TDATE="$(kid3-cli -c "get DATE" "$TARGET")"
                    TALBARTIST="$(kid3-cli -c "get ALBUMARTIST" "$TARGET")"

                    if [[ "${TARGET: -3}" == mp3 ]]
                    then
                        TSRCMEDIA="$(kid3-cli -c "get TMED" "$TARGET")"
                    else
                        TSRCMEDIA="$(kid3-cli -c "get SOURCEMEDIA" "$TARGET")"
                    fi

                    TTRACKTOTAL="$(kid3-cli -c "get TRACKTOTAL" "$TARGET")"
                    TTOTALTRACKS="$(kid3-cli -c "get TOTALTRACKS" "$TARGET")"
                    TTRACK="$(kid3-cli -c "get TRACK" "$TARGET")"

                    COMMONALBUM+="$TALBUM"+++
                    COMMONDATE+="$TDATE"+++
                    COMMONSRCMEDIA+="$TSRCMEDIA"+++
                    COMMONALBUMARTIST+="$TALBARTIST"+++

                    # check if crucial tags are missing
                    if [[ $TALBUM == "" || $TDATE = "" || $TALBARTIST == "" ]]
                    then
                        echo "[cymusic] [ERROR] crucial tags missing missing"
                        exit 1
                    fi

                    # remove deprecated total tracks tag
                    if [[ "${TARGET: -4}" == flac ]] && [[ $TTRACKTOTAL != "" || $TTOTALTRACKS != "" ]]
                    then
                        metaflac --remove-tag=TRACKTOTAL "$IFILE"
                        metaflac --remove-tag=TOTALTRACKS "$IFILE"
                    fi
                    if [[ "${TARGET: -4}" == mp3 ]]
                    then
                        kid3-cli -c "set TRACK ${TTRACK%/*}" "$IFILE"
                    fi

                    # copy UNSYNCEDLYRICS to LYRICS
                    # TODO
                fi
            done

            # check for inconsistant word count for all common tags ALBUM, DATE, ALBUMARTIST and SOURCEMEDIA
            if [[ $(echo "${COMMONALBUM::-3}" | sed "s/+++/\n/g" | sort | uniq -c | sort -n -r | cut -f1 -d " " | uniq | wc -l) != 1 ]]
            then
                echo "[cymusic] [ERROR] inconsistant common album word count dump"
                echo "${COMMONALBUM::-3}" | sed "s/+++/\n/g" | sort | uniq -c | sort -n -r
                exit 1
            elif [[ $(echo "${COMMONDATE::-3}" | sed "s/+++/\n/g" | sort | uniq -c | sort -n -r | cut -f1 -d " " | uniq | wc -l) != 1 ]]
            then
                echo "[cymusic] [ERROR] inconsistant common date year count dump"
                echo "${COMMONDATE::-3}" | sed "s/+++/\n/g" | sort | uniq -c | sort -n -r
                exit 1
            elif [[ $(echo "${COMMONSRCMEDIA::-3}" | sed "s/+++/\n/g" | sort | uniq -c | sort -n -r | cut -f1 -d " " | uniq | wc -l) != 1 ]]
            then
                echo "[cymusic] [ERROR] inconsistant common sourcemedia word count dump"
                echo "${COMMONSRCMEDIA::-3}" | sed "s/+++/\n/g" | sort | uniq -c | sort -n -r
                exit 1
            elif [[ $(echo "${COMMONALBUMARTIST::-3}" | sed "s/+++/\n/g" | sort | uniq -c | sort -n -r | cut -f1 -d " " | uniq | wc -l) != 1 ]]
            then
                echo "[cymusic] [ERROR] inconsistant common albumartist word count dump"
                echo "${COMMONALBUMARTIST::-3}" | sed "s/+++/\n/g" | sort | uniq -c | sort -n -r
                exit 1
            fi
            COMMONALBUM=""
            COMMONDATE=""
            COMMONSRCMEDIA=""
            COMMONALBUMARTIST=""

            # read basic metadata
            echo "[cymusic] using $TARGET as metadata provider"
            TAGALBUM=$(kid3-cli -c "get ALBUM" "$TARGET")
            TAGALBUMARTIST=$(kid3-cli -c "get ALBUMARTIST" "$TARGET")
            TAGDATE=$(kid3-cli -c "get DATE" "$TARGET")
            if [[ "${TARGET: -3}" == "mp3" ]]
            then
                TAGSRCMEDIA="$(kid3-cli -c "get TMED" "$TARGET")"
            else
                TAGSRCMEDIA="$(kid3-cli -c "get SOURCEMEDIA" "$TARGET")"
            fi

            echo "[cymusic] detected album: $TAGALBUM"
            echo "[cymusic] detected album artist: $TAGALBUMARTIST"
            echo "[cymusic] detected release date: $TAGDATE"
            echo "[cymusic] detected source media: $TAGSRCMEDIA"

            # set missing SOURCEMEDIA tag based on total tracks
            if [[ "$TAGSRCMEDIA" == "" ]]
            then
                if [[ $TRACKS -lt 5 ]]
                then
                    echo "[cymusic] writing missing SOURCEMEDIA tag to \"Single\" for all files"
                    kid3-cli -c "set SOURCEMEDIA Single" "$ITEMDIR"/*
                    kid3-cli -c "set TMED Single" "$ITEMDIR"/*.mp3 &> /dev/null
                    TAGSRCMEDIA="Single"
                else
                    echo "[cymusic] writing missing SOURCEMEDIA tag to \"Album\" for all files"
                    kid3-cli -c "set SOURCEMEDIA Album" "$ITEMDIR"/*
                    kid3-cli -c "set TMED Album" "$ITEMDIR"/*.mp3 &> /dev/null
                    TAGSRCMEDIA="Album"
                fi
            fi
            kid3-cli -c "set SOURCEMEDIA ''" "$ITEMDIR"/*.mp3 &> /dev/null
            kid3-cli -c "set SOURCEMEDIA ''" "$ITEMDIR"/*.mp3 &> /dev/null
            
            # write missing cover file to ITEMDIR if needed
            if ! [ -f "$ITEMDIR"/cover.png ] && ! [ -f "$ITEMDIR"/cover.jpg ]
            then
                echo "[cymusic] writing missing cover.png..."
                kid3-cli -c "get picture:\"$ITEMDIR/cover.png\"" "$TARGET" &> /dev/null
            else
                echo "[cymusic] detected cover file"
            fi

            # set correct file naming based on SOURCEMEDIA and various artist property
            echo "[cymusic] renaming files to correct format"
            if [[ "$TAGALBUMARTIST" == "Various Artists" ]]
            then
                kid3-cli -c "fromtag '%{artist} - %{title}'" "$ITEMDIR"/*
            elif [[ "$TAGSRCMEDIA" == "Single" ]]
            then
                kid3-cli -c "fromtag '%{albumartist} - %{title}'" "$ITEMDIR"/*
            elif [[ "$TAGSRCMEDIA" == "Album" || "$TAGSRCMEDIA" == "EP" || "$TAGSRCMEDIA" == "LP" ]]
            then
                kid3-cli -c "fromtag '%{albumartist} - %{album} - %{track} - %{title}'" "$ITEMDIR"/*
            elif [[ "$TAGSRCMEDIA" == "Compilation" ]]
            then
                kid3-cli -c "fromtag '%{albumartist} - %{album} - %{track} - %{artist} - %{title}'" "$ITEMDIR"/*
            fi

            # detox filenames
            # TODO

            # set correct folder naming
            FOLDERNAME="$TAGDATE - [$TAGSRCMEDIA] $(echo "$TAGALBUM" | sed 's/\///g')"
            if [[ ! -d "$1/$FOLDERNAME" ]]
            then
                echo "[cymusic] renaming $ITEMDIR -> $FOLDERNAME"
                mv "$ITEMDIR" "$1/$FOLDERNAME" || exit 1
            else
                echo "[cymusic] folder name is already in correct format"
            fi
        fi
    done
}

procplaylist () {    
    echo "[cymusic] copying numbered tracks to output src folder"
    mkdir -p "$OUTDIR"/src
    mkdir -p "$OUTDIR"/flac
    mkdir -p "$OUTDIR"/wav
    PL="$(basename "$PLAYLIST")"
    PTRACK=1
    while read l
    do
        cp -v "$l" "$OUTDIR/src/$PTRACK.${l##*.}" || exit 1
        (( PTRACK++ ))
    done < "$1"

    echo "[cymusic] applying playlist metadata"
    kid3-cli -c "numbertracks" "$OUTDIR"/src/*
    kid3-cli -c "set SOURCEMEDIA Playlist" "$OUTDIR"/src/*
    kid3-cli -c "set ALBUM '${PL%.*}'" "$OUTDIR"/src/*
    kid3-cli -c "set ALBUMARTIST CY" "$OUTDIR"/src/*
    kid3-cli -c "set DATE $(date +%Y)" "$OUTDIR"/src/*
    kid3-cli -c "set picture ''" "$OUTDIR"/src/*

    echo "[cymusic] renaming src folder"
    kid3-cli -c "fromtag '%{track}. %{artist} - %{title}'" "$OUTDIR"/src/*

    echo "[cymusic] copying tracks to output flac and wav folders"
    for s in "$OUTDIR"/src/*
    do
        TNAME=$(basename "$s")
        cp -v "$s" "${OUTDIR}/flac/temp_$TNAME"
        cp -v "$s" "${OUTDIR}/wav/temp_${TNAME:: 2}.${TNAME##*.}"
    done

    echo "[cymusic] EBU -23 LUFS dynamic normalizing to LRA 8, 16bit, 48kHz flac files (soxr resampler, triangular_hp dithering)"
    for f in "$OUTDIR"/flac/temp_*
    do
        TNAME=$(basename "$f")
        TNAME=${TNAME: 5}
        echo "$TNAME"
        ffmpeg-normalize "$f" -e "-resampler soxr -dither_method triangular_hp -sample_fmt s16" \
        -c:a flac -ar 48000 -nt ebu -t "-23" --dynamic -lrt 8 -o "${OUTDIR}/flac/$(sed s/\.${TNAME##*.}/\.flac/g <<< $TNAME)"
        rm "$f"
    done

    echo "[cymusic] EBU -23 LUFS dynamic normalizing to LRA 8, 16bit, 44.1kHz wav files (soxr resampler, triangular_hp dithering)"
    for w in "$OUTDIR"/wav/temp_*
    do
        TNAME=$(basename "$w")
        TNAME=${TNAME: 5}
        echo "$TNAME"
        ffmpeg-normalize "$w" -e "-resampler soxr -dither_method triangular_hp -sample_fmt s16" \
        -c:a pcm_s16le -ar 44100 -nt ebu -t "-23" --dynamic -lrt 8 -o "${OUTDIR}/wav/$(sed s/\.${TNAME##*.}/\.wav/g <<< $TNAME)"
        rm "$w"
    done
}

set_output_directory () {
	if [ ! -d "$1" ]
	then
		mkdir -p "$1"
	fi
	if [ -z "$(ls -A "$1")" ]
	then
		OUTDIR="$1"
	else
		echo "[cymusic] [ERROR] invalid output directory (must be empty!): $1"
		exit 1
	fi
}

echo "cymusic version $VERSION"

# Get user input flags
while getopts b:p:o:h OPTION
do
	case "${OPTION}"
	in
		h) print_help ;;
		b) BULK="$(readlink -f "${OPTARG}")" ;;
		p) PLAYLIST="$(readlink -f "${OPTARG}")" ;;
        o) set_output_directory "$(readlink -f "${OPTARG}")" ;;
	esac
done

if [[ -d "$BULK" ]]
then
    for AFOLDER in "$BULK"/*
    do
        ARTISTFOLDER="$(readlink -f "$AFOLDER")"
        if [[ -d "$ARTISTFOLDER" ]]
        then
            echo "[cymusic] reading items in $ARTISTFOLDER"
            procartist "$ARTISTFOLDER"
        else
            echo "[cymusic] [ERROR] \$1 not a directory: $ARTISTFOLDER"
            exit 1
        fi
    done
elif [[ -f "$PLAYLIST" ]]
then
    if [[ "${PLAYLIST: -3}" == m3u ]]
    then
        procplaylist "$PLAYLIST"
    else
        echo "[cymusic] [ERROR] not a playlist: $PLAYLIST"
        exit 1
    fi
fi
